if not DpsDashboard then
  DpsDashboard = { };
end

DpsDashboard.Dash = { };
DpsDashboard.Dash.Frame = nil;
DpsDashboard.Dash.FrameBackground = nil;
DpsDashboard.Dash.flashing = nil;
DpsDashboard.Dash.Locked = nil;
DpsDashboard.Dash.Configured = nil;
DpsDashboard.Dash.LastUpdate = 0;
DpsDashboard.damagetotal = 0;
DpsDashboard.healingtotal = 0;
DpsDashboard.dps = 0;
DpsDashboard.hps = 0;
DpsDashboard.damage = {};
DpsDashboard.healing = {};
DpsDashboard.CalculateHps = nil;
DpsDashboard.CalculateDps = nil;
DpsDashboard.CheckTimeEvents = nil;
DpsDashboard.CheckStatEvents = nil;
DpsDashboard.Font = CreateFont("DpsDashboardFont");

DpsDashboard.ShowWhenOutOfCombat = nil;
DpsDashboard.HideWhenOutOfCombat = nil;
DpsDashboard.ConfigureWhenOutOfCombat = nil;

DPS_DASHBOARD_STAT_REGISTER = {};
DPS_DASHBOARD_STAT_TYPE_REGISTER = {};
DPS_DASHBOARD_UPDATE_NEVER = nil;
DPS_DASHBOARD_UPDATE_TIMED = 1;
DPS_DASHBOARD_UPDATE_STATS = 2;

DpsDashboard.StatEvents = {};
DpsDashboard.StatEvents["UNIT_RESISTANCES"] = 1;
DpsDashboard.StatEvents["UNIT_STATS"] = 1;
--DpsDashboard.StatEvents["UNIT_DAMAGE"] = 1;
--DpsDashboard.StatEvents["UNIT_RANGEDDAMAGE"] = 1;
--DpsDashboard.StatEvents["PLAYER_DAMAGE_DONE_MODS"] = 1;
--DpsDashboard.StatEvents["UNIT_ATTACK_SPEED"] = 1;
DpsDashboard.StatEvents["UNIT_ATTACK_POWER"] = 1;
DpsDashboard.StatEvents["UNIT_RANGED_ATTACK_POWER"] = 1;
--DpsDashboard.StatEvents["UNIT_ATTACK"] = 1;
DpsDashboard.StatEvents["COMBAT_RATING_UPDATE"] = 1;

DpsDashboard.StatElements = {};
DpsDashboard.StatElements["first"] = 1;
DpsDashboard.StatElements["second"] = 1;
DpsDashboard.StatElements["third"] = 1;

local format = _G.format;
local bit_bor = _G.bit.bor
local bit_band = _G.bit.band

if not DpsDashboardOptions then
  DpsDashboardOptions = { };
  DpsDashboardOptions["fontsize"] = 24;
  DpsDashboardOptions["updateinterval"] = 0.3;
  DpsDashboardOptions["dpstime"] = 5;
	DpsDashboardOptions["hpstime"] = 30;
	DpsDashboardOptions["dashalpha"] = 25;
  DpsDashboardOptions["showdash"] = true;
  DpsDashboardOptions["dashlocked"] = nil;
	DpsDashboardOptions["checkdebuffs"] = false;
	DpsDashboardOptions["targetdebufftype"] = "Poison";
	DpsDashboardOptions["first"] = "meleecrit";
	DpsDashboardOptions["second"] = "meleeattackpower";
	DpsDashboardOptions["third"] = "empty";
end

local COMBATLOG_OBJECT_AFFILIATION_MINE = _G.COMBATLOG_OBJECT_AFFILIATION_MINE;
local COMBATLOG_OBJECT_REACTION_FRIENDLY = _G.COMBATLOG_OBJECT_REACTION_FRIENDLY;
local COMBATLOG_OBJECT_CONTROL_PLAYER = _G.COMBATLOG_OBJECT_CONTROL_PLAYER;
local COMBATLOG_OBJECT_TYPE_ME = bit_bor(_G.COMBATLOG_OBJECT_TYPE_PLAYER, _G.COMBATLOG_OBJECT_TYPE_OBJECT);
local COMBATLOG_OBJECT_TARGET = _G.COMBATLOG_OBJECT_TARGET;

------------------------------------
-- Event Functions
------------------------------------

DpsDashboard.OnLoad = function()
  DpsDashboard_Dash:RegisterEvent("VARIABLES_LOADED");
  DpsDashboard_Dash:RegisterEvent("PLAYER_TARGET_CHANGED");
  DpsDashboard_Dash:RegisterEvent("PLAYER_REGEN_ENABLED");
  
	DpsDashboard_Dash:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED");
	
  --Set up the slash command
  SLASH_DpsDashboard1 = "/dd";
  SlashCmdList["DpsDashboard"] = DpsDashboard.SlashHandler;
end

DpsDashboard.OnEvent = function(event, ...)
  if event == "VARIABLES_LOADED" then
    DpsDashboard.InitializeVariables();
    local menu = getglobal("DpsDashboardOptionPanelFirstInfoMenu");
    if menu then
      DpsDashboard.InfoMenuLoad(menu, "first");
    end
    menu = getglobal("DpsDashboardOptionPanelSecondInfoMenu");
    if menu then
      DpsDashboard.InfoMenuLoad(menu, "second");
    end
    menu = getglobal("DpsDashboardOptionPanelThirdInfoMenu");
    if menu then
      DpsDashboard.InfoMenuLoad(menu, "third");
    end
    return;
  end
  
  if not DpsDashboardOptions["showdash"] then
    return;
  end
  
  if event == "PLAYER_TARGET_CHANGED" then
    DpsDashboard.CheckTargetBuffs();
    if UnitExists("target") then
      local unitLevel = UnitLevel("target");
      if unitLevel < 0 then
        unitLevel = UnitLevel("player") + 3;
      end
      DpsDashboard.TargetLevel = unitLevel;
    else
      DpsDashboard.TargetLevel = UnitLevel("player");
    end
  elseif event == "PLAYER_REGEN_ENABLED" then
  	if InCombatLockdown() == nil then
  		if DpsDashboard.ConfigureDashWhenOutOfCombat then
  			DpsDashboard.ConfigureDash();
  		end
  		
  		if DpsDashboard.Dash.Configured ~= nil then
	  	  if DpsDashboard.ShowWhenOutOfCombat then
	  	    DpsDashboard.Dash.Frame:Show();
          DpsDashboard.ShowWhenOutOfCombat = nil;
	  	  elseif DpsDashboard.HideWhenOutOfCombat then
          DpsDashboard.Dash.Frame:Hide();
          DpsDashboard.HideWhenOutOfCombat = nil;
	  	  end
	  	end
	  end
  elseif event == "COMBAT_LOG_EVENT_UNFILTERED" then
  	DpsDashboard.CombatLogEvent(...);
  elseif DpsDashboard.StatEvents[event] and DpsDashboard.CheckStatEvents then
    DpsDashboard.UpdateStats(DPS_DASHBOARD_UPDATE_STATS);
  end
end

DpsDashboard.UpdateDashVisibility = function()
  if DpsDashboardOptions["showdash"] then
  	if InCombatLockdown() == nil then
  	  DpsDashboard.Dash.Frame:Show();
  	  DpsDashboard.UpdateStats(DPS_DASHBOARD_UPDATE_STATS);
  	  DpsDashboard.UpdateStats(DPS_DASHBOARD_UPDATE_TIMED);
  	  DpsDashboard.UpdateStats(DPS_DASHBOARD_UPDATE_NEVER);
  	else
  		DpsDashboard.HideWhenOutOfCombat = nil;
  		DpsDashboard.ShowWhenOutOfCombat = true;
  	end
  else
    if InCombatLockdown() == nil then
    	DpsDashboard.Dash.Frame:Hide();
    else
    	DpsDashboard.ShowWhenOutOfCombat = nil;
    	DpsDashboard.HideWhenOutOfCombat = true;
    end
  end
end

local index, val, dpsCutoff, hpsCutoff;
local counter;
DpsDashboard.OnUpdate = function(elapsed)
  DpsDashboard.Dash.LastUpdate = DpsDashboard.Dash.LastUpdate + elapsed;
  if DpsDashboard.CheckTimeEvents and (DpsDashboard.Dash.LastUpdate > DpsDashboardOptions["updateinterval"]) then
    dpsCutoff = time() - DpsDashboardOptions["dpstime"];
    hpsCutoff = time() - DpsDashboardOptions["hpstime"];
    
    counter = 0;
    for index, val in ipairs(DpsDashboard.damage) do
      if val[1] >= dpsCutoff then
        break;
      end
      DpsDashboard.damagetotal = DpsDashboard.damagetotal - val[2];
      counter = counter + 1;
    end
    while counter > 0 do
      tremove(DpsDashboard.damage, 1);
      counter = counter - 1;
    end
    DpsDashboard.dps = floor((DpsDashboard.damagetotal / DpsDashboardOptions["dpstime"]) + 0.5);
    
    for index, val in ipairs(DpsDashboard.healing) do
      if val[1] >= hpsCutoff then
        break;
      end
      DpsDashboard.healingtotal = DpsDashboard.healingtotal - val[2];
      counter = counter + 1;
    end
    while counter > 0 do
      tremove(DpsDashboard.healing, 1);
      counter = counter - 1;
    end
    DpsDashboard.hps = floor((DpsDashboard.healingtotal / DpsDashboardOptions["hpstime"]) + 0.5);
  
    DpsDashboard.UpdateStats(DPS_DASHBOARD_UPDATE_TIMED);
    DpsDashboard.Dash.LastUpdate = 0;
  end  	
end

DpsDashboard.CombatLogEvent = function(timestamp, event, srcGUID, srcName, srcFlags, dstGUID, dstName, dstFlags, ...)
  if DpsDashboardOptions["checkdebuffs"] and (strsub(event, 1, 10) == "SPELL_AURA") then
    if bit_band(dstFlags, COMBATLOG_OBJECT_TARGET) ~= 0 then
      DpsDashboard.CheckTargetBuffs();
    end
  end
  
  if bit_band(srcFlags, COMBATLOG_OBJECT_AFFILIATION_MINE) == 0 or
     bit_band(srcFlags, COMBATLOG_OBJECT_REACTION_FRIENDLY) == 0 or
     bit_band(srcFlags, COMBATLOG_OBJECT_CONTROL_PLAYER) == 0 or
     bit_band(srcFlags, COMBATLOG_OBJECT_TYPE_ME) == 0 then
	  return;
	end
  
	local found = nil;
	local amount = 0;
	local powerType;
	
  if DpsDashboard.CalculateDps then
    if ( event == "SWING_DAMAGE" ) then 
			amount = ...
			found = true;
		elseif (event == "SPELL_PERIODIC_DRAIN") or (event == "SPELL_PERIODIC_LEECH") or (event == "SPELL_DRAIN") or (event == "SPELL_LEECH") then
			amount, powerType = select(4, ...);
			found = true;
	
			if powerType ~= -2 then
				amount = 0;
			end	
		elseif (event == "SPELL_DAMAGE") or (event == "SPELL_PERIODIC_DAMAGE") or (event == "SPELL_EXTRA_ATTACKS") or (event == "RANGE_DAMAGE") or (event == "DAMAGE_SHIELD") then
			amount = select(4, ...);
			found = true;
		end
		
		if found and (amount > 0) then
			DpsDashboard.damagetotal = DpsDashboard.damagetotal + amount;
			
		  index = #(DpsDashboard.damage);
		  val = nil;
		  while index > 0 do
		    if DpsDashboard.damage[index][1] < timestamp then
				  tinsert(DpsDashboard.damage, index+1, {timestamp, amount});
				  val = true;
				  break;
				end
				index = index - 1;
			end
			
			if not val then
			  tinsert(DpsDashboard.damage, {timestamp, amount});
			end
		end
  end
  
  if (not found) and DpsDashboard.CalculateHps then
    if ( event == "SPELL_HEAL" ) then
			amount = select(4, ...);
			found = true;
	  elseif ( event == "SPELL_PERIODIC_HEAL" ) then
			amount = select(4, ...);
			found = true;
		elseif ( event == "SPELL_PERIODIC_ENERGIZE" ) then 
			amount, powerType = select(4, ...);
			found = true;
			
			if powerType ~= -2 then
				amount = 0;
			end			
		end
		
		if found and (amount > 0) then
			DpsDashboard.healingtotal = DpsDashboard.healingtotal + amount;
			
		  index = #(DpsDashboard.healing);
		  val = nil;
		  while index > 0 do
		    if DpsDashboard.healing[index][1] < timestamp then
				  tinsert(DpsDashboard.healing, index+1, {timestamp, amount});
				  val = true;
				  break;
				end
				index = index - 1;
			end
			
			if not val then
			  tinsert(DpsDashboard.healing, {timestamp, amount});
			end
		end
  end
end

DpsDashboard.SetDpsTime = function(dpstime)
  DpsDashboardOptions["dpstime"] = dpstime;
end

DpsDashboard.SetHpsTime = function(hpstime)
  DpsDashboardOptions["hpstime"] = hpstime;
end

local buffCount, buffName, buffType;
DpsDashboard.CheckTargetBuffs = function()
  buffCount = 1;
  buffName, _, _, _, buffType = UnitDebuff("target", buffCount);
  while buffName do
    if buffType == DpsDashboardOptions["targetdebufftype"] then
      DpsDashboard.StartFlashing();
      return;
    end
    buffCount = buffCount + 1;
    buffName, _, _, _, buffType = UnitDebuff("target", buffCount);
  end
  DpsDashboard.StopFlashing();
end;

DpsDashboard.RegisterStatUpdates = function()
  for key, _ in pairs(DpsDashboard.StatEvents) do
    DpsDashboard_Dash:RegisterEvent(key);
  end
end

DpsDashboard.UnregisterStatUpdates = function()
  for key, _ in pairs(DpsDashboard.StatEvents) do
    DpsDashboard_Dash:UnregisterEvent(key);
  end
end

------------------------------------
-- Default Stat Update Functions (the rest are in Stats.lua)
------------------------------------

local updateFunc = nil;
DpsDashboard.UpdateStats = function(updateType)
  if DPS_DASHBOARD_STAT_TYPE_REGISTER[DpsDashboardOptions["first"]] == updateType then
    updateFunc = DPS_DASHBOARD_STAT_REGISTER[DpsDashboardOptions["first"]];
    if updateFunc then
      DpsDashboardFirst:SetText(updateFunc());
    end
  end
  
  if DPS_DASHBOARD_STAT_TYPE_REGISTER[DpsDashboardOptions["second"]] == updateType then
    updateFunc = DPS_DASHBOARD_STAT_REGISTER[DpsDashboardOptions["second"]];
    if updateFunc then
      DpsDashboardSecond:SetText(updateFunc());
    end
  end
  
  if DPS_DASHBOARD_STAT_TYPE_REGISTER[DpsDashboardOptions["third"]] == updateType then
    updateFunc = DPS_DASHBOARD_STAT_REGISTER[DpsDashboardOptions["third"]];
    if updateFunc then
      DpsDashboardThird:SetText(updateFunc());
    end
  end
end

------------------------------------
-- Flash Functions
------------------------------------

DpsDashboard.StartFlashing = function()
  if DpsDashboard.Dash.flashing == nil then
    DpsDashboard.Dash.flashing = true;
    DpsDashboard.UIFrameFlash(DpsDashboard_Flash, 0.5, 0.5, -1);
  end
end

DpsDashboard.StopFlashing = function()		
  DpsDashboard.Dash.flashing = nil;
  DpsDashboard.UIFrameFlashRemoveFrame(DpsDashboard_Flash);
end

-- Function to start a frame flashing
DpsDashboard.UIFrameFlash = function(frame, fadeInTime, fadeOutTime, flashDuration, flashInHoldTime, flashOutHoldTime)
  if ( frame ) then
    -- Time it takes to fade in a flashing frame
    frame.fadeInTime = fadeInTime;
    -- Time it takes to fade out a flashing frame
    frame.fadeOutTime = fadeOutTime;
    -- How long to keep the frame flashing
    frame.flashDuration = flashDuration;
    -- Show the flashing frame when the fadeOutTime has passed
    frame.showWhenDone = nil;
    -- Internal duration timer
    frame.flashDurationTimer = 0;
    -- Internal timer
    frame.flashTimer = 0;
    -- Initial flash mode
    frame.flashMode = "IN";
    -- How long to hold the faded in state
    frame.flashInHoldTime = flashInHoldTime;
    -- How long to hold the faded out state
    frame.flashOutHoldTime = flashOutHoldTime;
    frame:SetAlpha(0.0);
    frame:SetScript("OnUpdate", DpsDashboard.UIFrameFlashUpdate);
  end
end

-- Called every frame to update flashing frames
local flashFrameAlpha = nil;
DpsDashboard.UIFrameFlashUpdate = function(frame, elapsed)
  frame.flashDurationTimer = frame.flashDurationTimer + elapsed;
  
  -- If flashDuration is exceeded
  if ( (frame.flashDurationTimer > frame.flashDuration) and frame.flashDuration ~= -1 ) then
    DpsDashboard.UIFrameFlashRemoveFrame(frame);
    frame.flashDurationTimer = nil;
  elseif ( frame.flashMode == "IN" ) then
    flashFrameAlpha = frame.flashTimer / frame.fadeInTime;
    frame:SetAlpha(flashFrameAlpha);
    if ( frame.flashTimer >= frame.fadeInTime ) then
      if ( frame.flashInHoldTime and frame.flashInHoldTime > 0 ) then
        frame.flashMode = "IN_HOLD";
      else
        frame.flashMode = "OUT";
      end
      frame.flashTimer = 0;
    else
      frame.flashTimer = frame.flashTimer + elapsed;
    end
  elseif ( frame.flashMode == "IN_HOLD" ) then
    frame:SetAlpha(1.0);
    if ( frame.flashTimer >= frame.flashInHoldTime ) then
      frame.flashMode = "OUT";
      frame.flashTimer = 0;
    else
      frame.flashTimer = frame.flashTimer + elapsed;
    end
  elseif ( frame.flashMode == "OUT" ) then
    flashFrameAlpha = 1.0 - frame.flashTimer / frame.fadeOutTime;
    frame:SetAlpha(flashFrameAlpha);
    if ( frame.flashTimer >= frame.fadeOutTime ) then	
      if ( frame.flashOutHoldTime and frame.flashOutHoldTime > 0 ) then	
        frame.flashMode = "OUT_HOLD";
      else
          frame.flashMode = "IN";
      end
      frame.flashTimer = 0;
    else
      frame.flashTimer = frame.flashTimer + elapsed;
    end
    frame:SetAlpha(flashFrameAlpha);
  elseif ( frame.flashMode == "OUT_HOLD" ) then
    frame:SetAlpha(0.0);
    frame.flashTimer = frame.flashTimer + elpased;
    if ( frame.flashTimer >= frame.flashOutHoldTime ) then
      frame.flashMode = "IN";
      frame.flashTimer = 0;
    else
      frame.flashTimer = frame.flashTimer + elapsed;
    end
  end
end 

DpsDashboard.UIFrameFlashRemoveFrame = function(frame)
  frame:SetScript("OnUpdate", nil);
  frame:SetAlpha(0.0);
end

------------------------------
-- Dash functions
------------------------------

DpsDashboard.ConfigureDash = function()
  DpsDashboard.Dash.Frame = getglobal("DpsDashboard_Dash");
	if DpsDashboard.Dash.Frame ~= nil then
	  DpsDashboard.Dash.FrameBackground = getglobal("DpsDashboardDashBackground");
	  if DpsDashboard.Dash.FrameBackground ~= nil then
	    DpsDashboard.Dash.FrameBackground:SetVertexColor(0,0,0);
	    DpsDashboard.Dash.FrameBackground:SetAlpha(DpsDashboardOptions["dashalpha"]/100.0);
	  end
	  
	  local flashFrame = getglobal("DpsDashboard_Flash");
	  if flashFrame ~= nil then
	  	flashFrame:SetAlpha(0.0);
	  end
	  
    if DpsDashboardOptions["height"] ~= nil then
      DpsDashboard.Dash.Frame:SetHeight(DpsDashboardOptions["height"]);
    end
    if DpsDashboardOptions["width"] ~= nil then
      DpsDashboard.Dash.Frame:SetWidth(DpsDashboardOptions["width"]);
    end
    
    local x = DpsDashboardOptions["x"];
    local y = DpsDashboardOptions["y"];
    if x ~= nil and y ~= nil then
      DpsDashboard.Dash.Frame:ClearAllPoints();
      DpsDashboard.Dash.Frame:SetPoint("BOTTOMLEFT", "UIParent", "BOTTOMLEFT", x, y);
    end
    
    if (DpsDashboardOptions["showdash"] == true) then
	    DpsDashboard.Dash.Frame:Show();
	  else
	    DpsDashboard.Dash.Frame:Hide();
	  end
	  
    DpsDashboard.Dash.Configured = true;
  end
end

DpsDashboard.SetDashAlpha = function(alphaValue)
  if alphaValue == nil then
    return;
  end
  if alphaValue < 0 or alphaValue > 100 then
    return;
  end
  
  DpsDashboardOptions["dashalpha"] = alphaValue;
  if DpsDashboard.Dash.FrameBackground ~= nil then
    DpsDashboard.Dash.FrameBackground:SetAlpha(alphaValue/100.0);
  end
end

DpsDashboard.SetDashVisibility = function(visible)
  local show = nil;
  if visible then
    show = true;
  end

  DpsDashboardOptions["showdash"] = show;
  local showDashCheck = getglobal("DpsDashboardOptionPanelshowdash");
  if showDashCheck then
    showDashCheck:SetChecked(show);
  end
  DpsDashboard.UpdateDashVisibility();
end

DpsDashboard.ResetDashPosition = function()
  if InCombatLockdown() == nil then
    if DpsDashboard.Dash.Frame ~= nil then
      DpsDashboard.Dash.Frame:ClearAllPoints();
      DpsDashboard.Dash.Frame:SetPoint("CENTER", "UIParent", "CENTER", 0, 0);
    end
  else
    DpsDashboard.Print(DPSDASHBOARD_FAILED_RESET);
  end
end

-----------------------------
-- MOD CONFIGURATION CODE
-----------------------------

DpsDashboard.Print = function(msg) --*
	if (DEFAULT_CHAT_FRAME) then
		DEFAULT_CHAT_FRAME:AddMessage(msg, 1.0, 1.0, 1.0);
	end
end

DpsDashboard.SlashHandler = function(command) --*
  local i,j, cmd, param = string.find(command, "^([^ ]+) (.+)$");

  -- nil prevention
  if (cmd == nil) then cmd = command; end
  if (not cmd) then cmd = command; end
  if (not cmd) then cmd = ""; end
  if (not param) then param = ""; end
	
  local upperCmd = string.upper(cmd);
  if (upperCmd == "SHOW") then
    DpsDashboardOptions["showdash"] = true;
    DpsDashboard.HideWhenOutOfCombat = nil;
    DpsDashboard.ShowWhenOutOfCombat = true;
    DpsDashboard.UpdateDashVisibility();
  elseif (upperCmd == "HIDE") then
    DpsDashboardOptions["showdash"] = nil;
    DpsDashboard.HideWhenOutOfCombat = true;
    DpsDashboard.ShowWhenOutOfCombat = nil;
    DpsDashboard.UpdateDashVisibility();
  elseif (upperCmd == "RESET") then
     DpsDashboard.ResetDashPosition();
  elseif (upperCmd == "LOCK") then
    local locked = nil;
    if DpsDashboardOptions["dashlocked"] == true then
    	locked = true;
    end
    DpsDashboard.SetDashLock(locked);
  elseif (upperCmd == "DEBUFF") then
    local upperParam = string.upper(param);
    if upperParam == "POISON" then
      DpsDashboardOptions["targetdebufftype"] = "Poison";
      DpsDashboard.Print(DPSDASHBOARD_TARGET_DEBUFF.."Poison");
    elseif upperParam == "MAGIC" then
      DpsDashboardOptions["targetdebufftype"] = "Magic";
      DpsDashboard.Print(DPSDASHBOARD_TARGET_DEBUFF.."Magic");
    elseif upperParam == "CURSE" then
      DpsDashboardOptions["targetdebufftype"] = "Curse";
      DpsDashboard.Print(DPSDASHBOARD_TARGET_DEBUFF.."Curse");
    elseif upperParam == "DISEASE" then
      DpsDashboardOptions["targetdebufftype"] = "Disease";
      DpsDashboard.Print(DPSDASHBOARD_TARGET_DEBUFF.."Disease");
    end
    DpsDashboard.CheckTargetBuffs();    
  elseif (string.sub(upperCmd, 1, 5) == "ALPHA") then
    if string.len(param) > 0 then
      local alphaValue = tonumber(param);
      DpsDashboard.SetDashAlpha(alphaValue);
      DpsDashboard.Print(DPSDASHBOARD_OPTIONSDISPLAY["ALPHACHANGE"] .. alphaValue .. "%");
    end
  elseif (upperCmd == "UPDATE") then
    local updateInterval = tonumber(param);
    if (updateInterval ~= nil) and (updateInterval < 5) and (updateInterval > 0) then
      DpsDashboardOptions["updateinterval"] = updateInterval;
      DpsDashboard.Print(DPSDASHBOARD_UPDATE_INTERVAL..updateInterval);
    else
    	DpsDashboard.Print(DPSDASHBOARD_UPDATE_INTERVAL_INVALID);
    end
  elseif (upperCmd == "FONT") then
    local size = tonumber(param);
    if (size ~= nil) and (size > 0) and (size < 50) then
      DpsDashboardOptions["fontsize"] = size;
      DpsDashboard.Font:SetFont("Fonts\\ARIALN.TTF", size, "OUTLINE");
		  DpsDashboardFirst:SetFontObject(DpsDashboard.Font);
		  DpsDashboardFirst:SetText(DpsDashboardFirst:GetText());
		  DpsDashboardSecond:SetFontObject(DpsDashboard.Font);
		  DpsDashboardThird:SetFontObject(DpsDashboard.Font);
		  DpsDashboard.Print(DPSDASHBOARD_FONT_SET..size);
		else
		  DpsDashboard.Print(DPSDASHBOARD_FONT_INVALID);
    end
  elseif ((cmd == "") or (cmd == "help")) then
	  DpsDashboard.Print(DPSDASHBOARD_USEAGE);
	end
end

DpsDashboard.SetBooleanOption = function(option, on)
  local setting = nil;
  if on then
    setting = true;
  end
  DpsDashboardOptions[option] = setting;
end

DpsDashboard.SetOption = function(option, on)
  DpsDashboardOptions[option] = on;
  
  if DpsDashboard.StatElements[option] then
    DpsDashboard.UpdateStats(DPS_DASHBOARD_STAT_TYPE_REGISTER[on]);
    DpsDashboard.CheckUpdateFlags();
  end
end

local statUpdateType;
DpsDashboard.CheckUpdateFlags = function()
  DpsDashboard.CheckTimeEvents = nil;
  DpsDashboard.CheckStatEvents = nil;
  DpsDashboard.CalculateDps = nil;
  DpsDashboard.CalculateHps = nil;
  
  statUpdateType = DPS_DASHBOARD_STAT_TYPE_REGISTER[DpsDashboardOptions["first"]];
  if statUpdateType == DPS_DASHBOARD_UPDATE_STATS then
    DpsDashboard.CheckStatEvents = true;
  elseif statUpdateType == DPS_DASHBOARD_UPDATE_TIMED then
    DpsDashboard.CheckTimeEvents = true;
  end
  if DpsDashboardOptions["first"] == "dps" then
    DpsDashboard.CalculateDps = true;
  elseif DpsDashboardOptions["first"] == "hps" then
    DpsDashboard.CalculateHps = true;
  end
  
  statUpdateType = DPS_DASHBOARD_STAT_TYPE_REGISTER[DpsDashboardOptions["second"]];
  if statUpdateType == DPS_DASHBOARD_UPDATE_STATS then
    DpsDashboard.CheckStatEvents = true;
  elseif statUpdateType == DPS_DASHBOARD_UPDATE_TIMED then
    DpsDashboard.CheckTimeEvents = true;
  end
  if DpsDashboardOptions["second"] == "dps" then
    DpsDashboard.CalculateDps = true;
  elseif DpsDashboardOptions["second"] == "hps" then
    DpsDashboard.CalculateHps = true;
  end
  
  statUpdateType = DPS_DASHBOARD_STAT_TYPE_REGISTER[DpsDashboardOptions["third"]];
  if statUpdateType == DPS_DASHBOARD_UPDATE_STATS then
    DpsDashboard.CheckStatEvents = true;
  elseif statUpdateType == DPS_DASHBOARD_UPDATE_TIMED then
    DpsDashboard.CheckTimeEvents = true;
  end
  if DpsDashboardOptions["third"] == "dps" then
    DpsDashboard.CalculateDps = true;
  elseif DpsDashboardOptions["third"] == "hps" then
    DpsDashboard.CalculateHps = true;
  end
  
  if DpsDashboard.CheckStatEvents then
    DpsDashboard.RegisterStatUpdates();
  else
    DpsDashboard.UnregisterStatUpdates();
  end
end

DpsDashboard.LoadOptions = function(frame)
  if frame then
    local frameName = frame:GetName();
    local frameItem = nil;
    for key, val in pairs(DpsDashboardOptions) do
      frameItem = getglobal(frameName..key);
      if frameItem ~= nil then
        if frameItem:IsFrameType("CheckButton") then
          frameItem:SetChecked(val);
	      end
      end
    end
    frameItem = getglobal(frameName.."dashalpha");
    if frameItem ~= nil then
      frameItem:SetMinMaxValues(0, 100);
      frameItem:SetValueStep(1);
      frameItem:SetValue(DpsDashboardOptions["dashalpha"]);
    end
    frameItem = getglobal(frameName.."dpstime");
    if frameItem ~= nil then
      frameItem:SetMinMaxValues(1, 30);
      frameItem:SetValueStep(1);
      frameItem:SetValue(DpsDashboardOptions["dpstime"]);
    end
    frameItem = getglobal(frameName.."hpstime");
    if frameItem ~= nil then
      frameItem:SetMinMaxValues(1, 30);
      frameItem:SetValueStep(1);
      frameItem:SetValue(DpsDashboardOptions["hpstime"]);
    end
  end
end

DpsDashboard.InitializeVariables = function()
  if DpsDashboardOptions == nil then
    DpsDashboardOptions = { };
    DpsDashboardOptions["fontsize"] = 24;
    DpsDashboardOptions["updateinterval"] = 0.3;
    DpsDashboardOptions["showdash"] = true;
    DpsDashboardOptions["dashlocked"] = nil;
		DpsDashboardOptions["checkdebuffs"] = false;
		DpsDashboardOptions["targetdebufftype"] = "Poison";
		DpsDashboardOptions["first"] = "meleecrit";
		DpsDashboardOptions["second"] = "meleeattackpower";
		DpsDashboardOptions["third"] = "empty";
  end

  if DpsDashboardOptions["fontsize"] == nil then
    DpsDashboardOptions["fontsize"] = 24;
  end
  
  if DpsDashboardOptions["updateinterval"] == nil then
    DpsDashboardOptions["updateinterval"] = 0.3;
  end
  
	if DpsDashboardOptions["dpstime"] == nil then
		DpsDashboardOptions["dpstime"] = 5;
	end
	if DpsDashboardOptions["hpstime"] then
		DpsDashboardOptions["hpstime"] = 30;
	end
	
	if DpsDashboardOptions["dashalpha"] == nil then
		DpsDashboardOptions["dashalpha"] = 25;
	end
  
  DpsDashboard.Font:SetFont("Fonts\\ARIALN.TTF", DpsDashboardOptions["fontsize"], "OUTLINE");
  DpsDashboardFirst:SetFontObject(DpsDashboard.Font);
  DpsDashboardSecond:SetFontObject(DpsDashboard.Font);
  DpsDashboardThird:SetFontObject(DpsDashboard.Font);
    
  if InCombatLockdown() == nil then
  	DpsDashboard.ConfigureDash();
  else
  	DpsDashboard.ConfigureDashWhenOutOfCombat = true;
  end
  
  DpsDashboard.TargetLevel = UnitLevel("player");
  DpsDashboard.CheckUpdateFlags();
  DpsDashboard.UpdateStats(DPS_DASHBOARD_UPDATE_STATS);
  DpsDashboard.UpdateStats(DPS_DASHBOARD_UPDATE_TIMED);
  DpsDashboard.UpdateStats(DPS_DASHBOARD_UPDATE_NEVER);
end

DpsDashboard.SaveSize = function()
  if DpsDashboard.Dash.Frame ~= nil then
    DpsDashboardOptions["height"] = DpsDashboard.Dash.Frame:GetHeight();
    DpsDashboardOptions["width"] = DpsDashboard.Dash.Frame:GetWidth();    
  end
end

DpsDashboard.SavePosition = function()
  if DpsDashboard.Dash.Frame ~= nil then
    DpsDashboardOptions["x"] = DpsDashboard.Dash.Frame:GetLeft();
    DpsDashboardOptions["y"] = DpsDashboard.Dash.Frame:GetTop();
  end
end

DpsDashboard.OffOrOn = function(val)
  if (val == nil) or (val == 0) then
    return DPSDASHBOARD_OPTIONS_OFF;
  else
    return DPSDASHBOARD_OPTIONS_ON;
  end
end

DpsDashboard.SetDashLock = function(lock)
  DpsDashboardOptions["dashlocked"] = lock;
  DpsDashboard.Print(DPSDASHBOARD_OPTIONSDISPLAY["lock"] .. DpsDashboard.OffOrOn(lock));
end

------------------------------------
-- Option Menu Functions
------------------------------------

DpsDashboard.InfoMenuLoad = function(frame, key)
  local initFunc = DpsDashboard["InfoMenuInitialize"..key];
  if initFunc then
    local optionVal = DpsDashboardOptions[key];
		local selectedVal = 0;
		for orderkey, val in pairs(DPSDASHBOARD_MENU_ORDER) do
		  if val == optionVal then
		    selectedVal = orderkey;
		    break;
		  end
		end
    frame.defaultValue = "empty";
		frame.value = selectedVal;
		frame.currValue = frame.selectedVal;
		frame.tooltip = DPSDASHBOARD_OPTIONS_MENU_TOOLTIPS[optionVal];
		
		UIDropDownMenu_SetWidth(frame, 140);
		UIDropDownMenu_Initialize(frame, initFunc);
		UIDropDownMenu_SetSelectedValue(frame, selectedVal);

		frame.SetValue = 
			function (self, value)
			  self.value = value;
				UIDropDownMenu_SetSelectedValue(self, value);
				DpsDashboard.SetOption(key, DPSDASHBOARD_MENU_ORDER[value]);
				self.tooltip = DPSDASHBOARD_OPTIONS_MENU_TOOLTIPS[DPSDASHBOARD_MENU_ORDER[value]];
			end
		frame.GetValue =
			function (self)
				return UIDropDownMenu_GetSelectedValue(self);
			end
		frame.RefreshValue =
			function (self)
				UIDropDownMenu_Initialize(self, initFunc);
				UIDropDownMenu_SetSelectedValue(self, self.value);
			end
	end
end

DpsDashboard.InfoMenuClickFirst = function(self)
	DpsDashboardOptionPanelFirstInfoMenu:SetValue(self.value);
end

DpsDashboard.InfoMenuClickSecond = function(self)
	DpsDashboardOptionPanelSecondInfoMenu:SetValue(self.value);
end

DpsDashboard.InfoMenuClickThird = function(self)
	DpsDashboardOptionPanelThirdInfoMenu:SetValue(self.value);
end

DpsDashboard.InfoMenuInitializefirst = function()
	local selectedValue = UIDropDownMenu_GetSelectedValue(DpsDashboardOptionPanelFirstInfoMenu);
	local info = UIDropDownMenu_CreateInfo();
	info.func = DpsDashboard.InfoMenuClickFirst;
	
	for key, val in pairs(DPSDASHBOARD_MENU_ORDER) do
	  info.text = DPSDASHBOARD_OPTIONS_MENU_TEXT[val];
	  info.value = key;
	  if ( info.value == selectedValue ) then
			info.checked = 1;
		else
			info.checked = nil;
		end
		info.tooltipTitle = info.text;
		info.tooltipText = DPSDASHBOARD_OPTIONS_MENU_TOOLTIPS[val];
		UIDropDownMenu_AddButton(info);
	end
end

DpsDashboard.InfoMenuInitializesecond = function()
	local selectedValue = UIDropDownMenu_GetSelectedValue(DpsDashboardOptionPanelSecondInfoMenu);
	local info = UIDropDownMenu_CreateInfo();
	info.func = DpsDashboard.InfoMenuClickSecond;
	
	for key, val in pairs(DPSDASHBOARD_MENU_ORDER) do
	  info.text = DPSDASHBOARD_OPTIONS_MENU_TEXT[val];
	  info.value = key;
	  if ( info.value == selectedValue ) then
			info.checked = 1;
		else
			info.checked = nil;
		end
		info.tooltipTitle = info.text;
		info.tooltipText = DPSDASHBOARD_OPTIONS_MENU_TOOLTIPS[val];
		UIDropDownMenu_AddButton(info);
	end
end

DpsDashboard.InfoMenuInitializethird = function()
	local selectedValue = UIDropDownMenu_GetSelectedValue(DpsDashboardOptionPanelThirdInfoMenu);
	local info = UIDropDownMenu_CreateInfo();
	info.func = DpsDashboard.InfoMenuClickThird;
	
	for key, val in pairs(DPSDASHBOARD_MENU_ORDER) do
	  info.text = DPSDASHBOARD_OPTIONS_MENU_TEXT[val];
	  info.value = key;
	  if ( info.value == selectedValue ) then
			info.checked = 1;
		else
			info.checked = nil;
		end
		info.tooltipTitle = info.text;
		info.tooltipText = DPSDASHBOARD_OPTIONS_MENU_TOOLTIPS[val];
		UIDropDownMenu_AddButton(info);
	end
end